home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / TUTOROOT.PAK / STEP10.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  11KB  |  478 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1994 by Borland International
  3. //   Tutorial application -- step10.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl/pch.h>
  6. #include <owl/applicat.h>
  7. #include <owl/decframe.h>
  8. #include <owl/dc.h>
  9. #include <owl/inputdia.h>
  10. #include <owl/opensave.h>
  11. #include <owl/controlb.h>
  12. #include <owl/buttonga.h>
  13. #include <owl/statusba.h>
  14. #include <owl/gdiobjec.h>
  15. #include <owl/chooseco.h>
  16. #include <classlib/arrays.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "step10.rc"
  20.  
  21. typedef TArray<TPoint> TPoints;
  22. typedef TArrayIterator<TPoint> TPointsIterator;
  23.  
  24. class TLine : public TPoints {
  25.   public:
  26.     // Constructor to allow construction from a color and a pen size.
  27.     // Also serves as default constructor.
  28.     TLine(const TColor& color = TColor(0), int penSize = 1) :
  29.       TPoints(10, 0, 10), PenSize(penSize), Color(color) {}
  30.  
  31.     // Functions to modify and query pen attributes.
  32.     int QueryPenSize() const
  33.     {
  34.       return PenSize;
  35.     }
  36.  
  37.     TColor& QueryColor()
  38.     {
  39.       return Color;
  40.     }
  41.  
  42.     void SetPen(const TColor& newColor, int penSize = 0);
  43.     void SetPen(int penSize);
  44.  
  45.     // TLine draws itself.  Returns true if everything went OK.
  46.     virtual bool Draw(TDC&) const;
  47.  
  48.     // The == operator must be defined for the container class, even if unused
  49.     bool operator ==(const TLine& other) const
  50.     {
  51.       return &other == this;
  52.     }
  53.  
  54.     friend ostream& operator <<(ostream& os, const TLine& line);
  55.     friend istream& operator >>(istream& is, TLine& line);
  56.  
  57.   protected:
  58.     int PenSize;
  59.     TColor Color;
  60. };
  61.  
  62. void
  63. TLine::SetPen(int penSize)
  64. {
  65.   if (penSize < 1)
  66.     PenSize = 1;
  67.   else
  68.     PenSize = penSize;
  69. }
  70.  
  71. void
  72. TLine::SetPen(const TColor& newColor, int penSize)
  73. {
  74.   // If penSize isn't the default (0), set PenSize to the new size.
  75.   if (penSize)
  76.     PenSize = penSize;
  77.  
  78.   Color = newColor;
  79. }
  80.  
  81. bool
  82. TLine::Draw(TDC& dc) const
  83. {
  84.   // Set pen for the dc to the values for this line
  85.   TPen pen(Color, PenSize);
  86.   dc.SelectObject(pen);
  87.  
  88.   // Iterates through the points in the line i.
  89.   TPointsIterator j(*this);
  90.   bool first = true;
  91.  
  92.   while (j) {
  93.     TPoint p = j++;
  94.  
  95.     if (!first)
  96.       dc.LineTo(p);
  97.     else {
  98.       dc.MoveTo(p);
  99.       first = false;
  100.     }
  101.   }
  102.   dc.RestorePen();
  103.   return true;
  104. }
  105.  
  106. typedef TArray<TLine> TLines;
  107. typedef TArrayIterator<TLine> TLinesIterator;
  108.  
  109. class TDrawWindow : public TWindow {
  110.   public:
  111.     TDrawWindow(TWindow* parent = 0);
  112.    ~TDrawWindow()
  113.     {
  114.       delete DragDC;
  115.       delete Line;
  116.       delete Lines;
  117.       delete FileData;
  118.     }
  119.  
  120.   protected:
  121.     TDC* DragDC;
  122.     TPen* Pen;
  123.     TLines* Lines;
  124.     TLine* Line; // To hold a single line at a time that later gets
  125.                  // stuck in Lines
  126.     TOpenSaveDialog::TData* FileData;
  127.     bool IsDirty, IsNewFile;
  128.  
  129.     void GetPenSize(); // GetPenSize always calls Line->SetPen().
  130.  
  131.     // Override member function of TWindow
  132.     bool CanClose();
  133.  
  134.     // Message response functions
  135.     void EvLButtonDown(uint, TPoint&);
  136.     void EvRButtonDown(uint, TPoint&);
  137.     void EvMouseMove(uint, TPoint&);
  138.     void EvLButtonUp(uint, TPoint&);
  139.     void Paint(TDC&, bool, TRect&);
  140.     void CmFileNew();
  141.     void CmFileOpen();
  142.     void CmFileSave();
  143.     void CmFileSaveAs();
  144.     void CmPenSize();
  145.     void CmPenColor();
  146.     void CmAbout();
  147.     void SaveFile();
  148.     void OpenFile();
  149.  
  150.   DECLARE_RESPONSE_TABLE(TDrawWindow);
  151. };
  152.  
  153. DEFINE_RESPONSE_TABLE1(TDrawWindow, TWindow)
  154.   EV_WM_LBUTTONDOWN,
  155.   EV_WM_RBUTTONDOWN,
  156.   EV_WM_MOUSEMOVE,
  157.   EV_WM_LBUTTONUP,
  158.   EV_COMMAND(CM_FILENEW, CmFileNew),
  159.   EV_COMMAND(CM_FILEOPEN, CmFileOpen),
  160.   EV_COMMAND(CM_FILESAVE, CmFileSave),
  161.   EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
  162.   EV_COMMAND(CM_PENSIZE, CmPenSize),
  163.   EV_COMMAND(CM_PENCOLOR, CmPenColor),
  164.   EV_COMMAND(CM_ABOUT, CmAbout),
  165. END_RESPONSE_TABLE;
  166.  
  167. TDrawWindow::TDrawWindow(TWindow* parent)
  168. {
  169.   Init(parent, 0, 0);
  170.   DragDC    = 0;
  171.   Lines     = new TLines(5, 0, 5);
  172.   Line      = new TLine(TColor::Black, 1);
  173.   IsNewFile = true;
  174.   IsDirty   = false;
  175.   FileData  = new TOpenSaveDialog::TData(OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
  176.                                         "Point Files (*.PTS)|*.pts|", 0, "",
  177.                                         "PTS");
  178. }
  179.  
  180. bool
  181. TDrawWindow::CanClose()
  182. {
  183.   if (IsDirty)
  184.     switch(MessageBox("Do you want to save?", "Drawing has changed",
  185.                       MB_YESNOCANCEL | MB_ICONQUESTION)) {
  186.       case IDCANCEL:
  187.         // Choosing Cancel means to abort the close -- return false.
  188.         return false;
  189.  
  190.       case IDYES:
  191.         // Choosing Yes means to save the drawing.
  192.         CmFileSave();
  193.     }
  194.   return true;
  195. }
  196.  
  197. void
  198. TDrawWindow::EvLButtonDown(uint, TPoint& point)
  199. {
  200.   if (!DragDC) {
  201.     SetCapture();
  202.     DragDC = new TClientDC(*this);
  203.     Pen = new TPen(Line->QueryColor(), Line->QueryPenSize());
  204.     DragDC->SelectObject(*Pen);
  205.     DragDC->MoveTo(point);
  206.     Line->Add(point);
  207.     IsDirty = true;
  208.   }
  209. }
  210.  
  211. void
  212. TDrawWindow::EvRButtonDown(uint, TPoint&)
  213. {
  214.   GetPenSize();
  215. }
  216.  
  217. void
  218. TDrawWindow::EvMouseMove(uint, TPoint& point)
  219. {
  220.   if (DragDC) {
  221.     DragDC->LineTo(point);
  222.     Line->Add(point);
  223.   }
  224. }
  225.  
  226. void
  227. TDrawWindow::EvLButtonUp(uint, TPoint&)
  228. {
  229.   if (DragDC) {
  230.     ReleaseCapture();
  231.     Lines->Add(*Line);
  232.     Line->Flush();
  233.     delete DragDC;
  234.     delete Pen;
  235.     DragDC = 0;
  236.   }
  237. }
  238.  
  239. void
  240. TDrawWindow::CmPenSize()
  241. {
  242.   GetPenSize();
  243. }
  244.  
  245. void
  246. TDrawWindow::CmPenColor()
  247. {
  248.   TChooseColorDialog::TData colors;
  249.   static TColor custColors[16] =
  250.   {
  251.     0x010101L, 0x101010L, 0x202020L, 0x303030L,
  252.     0x404040L, 0x505050L, 0x606060L, 0x707070L,
  253.     0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
  254.     0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  255.   };
  256.  
  257.   colors.Flags = CC_RGBINIT;
  258.   colors.Color = TColor(Line->QueryColor());
  259.   colors.CustColors = custColors;
  260.   if (TChooseColorDialog(this, colors).Execute() == IDOK)
  261.     Line->SetPen(colors.Color);
  262. }
  263.  
  264. void
  265. TDrawWindow::GetPenSize()
  266. {
  267.   char inputText[6];
  268.   int penSize = Line->QueryPenSize();
  269.  
  270.   wsprintf(inputText, "%d", penSize);
  271.   if ((TInputDialog(this, "Line Thickness",
  272.                         "Input a new thickness:",
  273.                         inputText,
  274.                         sizeof(inputText))).Execute() == IDOK) {
  275.     penSize = atoi(inputText);
  276.  
  277.     if (penSize < 1)
  278.       penSize = 1;
  279.   }
  280.   Line->SetPen(penSize);
  281. }
  282.  
  283. void
  284. TDrawWindow::Paint(TDC& dc, bool, TRect&)
  285. {
  286.   // Iterates through the array of line objects.
  287.   TLinesIterator i(*Lines);
  288.  
  289.   while (i)
  290.     i++.Draw(dc);
  291. }
  292.  
  293. void
  294. TDrawWindow::CmFileNew()
  295. {
  296.   if (CanClose()) {
  297.     Line->Flush();
  298.     Lines->Flush();
  299.     Invalidate();
  300.     IsDirty = false;
  301.     IsNewFile = true;
  302.   }
  303. }
  304.  
  305. void
  306. TDrawWindow::CmFileOpen()
  307. {
  308.   if (CanClose())
  309.     if ((TFileOpenDialog(this, *FileData)).Execute() == IDOK)
  310.       OpenFile();
  311. }
  312.  
  313. void
  314. TDrawWindow::CmFileSave()
  315. {
  316.   if (IsNewFile)
  317.     CmFileSaveAs();
  318.   else
  319.     SaveFile();
  320. }
  321.  
  322. void
  323. TDrawWindow::CmFileSaveAs()
  324. {
  325.   if (IsNewFile)
  326.     strcpy(FileData->FileName, "");
  327.  
  328.   if ((TFileSaveDialog(this, *FileData)).Execute() == IDOK)
  329.     SaveFile();
  330. }
  331.  
  332. void
  333. TDrawWindow::CmAbout()
  334. {
  335.   TDialog(this, IDD_ABOUT).Execute();
  336. }
  337.  
  338. void
  339. TDrawWindow::SaveFile()
  340. {
  341.   ofstream os(FileData->FileName);
  342.  
  343.   if (!os)
  344.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  345.   else {
  346.     // Write the number of lines in the figure
  347.     os << Lines->GetItemsInContainer();
  348.  
  349.     // Append a description using a resource string
  350.     os << ' ' << string(*GetApplication(), IDS_FILEINFO) << '\n';
  351.  
  352.     // Get an iterator for the array of lines
  353.     TLinesIterator i(*Lines);
  354.  
  355.     // While the iterator is valid (i.e. we haven't run out of lines)
  356.     while (i)
  357.       // Copy the current line from the iterator and increment the array.
  358.       os << i++;
  359.  
  360.     // Set new file and dirty display indicator to false.
  361.     IsNewFile = IsDirty = false;
  362.   }
  363. }
  364.  
  365. void
  366. TDrawWindow::OpenFile()
  367. {
  368.   ifstream is(FileData->FileName);
  369.  
  370.   if (!is)
  371.     MessageBox("Unable to open file", "File Error", MB_OK | MB_ICONEXCLAMATION);
  372.   else {
  373.     unsigned numLines;
  374.     char fileinfo[100];
  375.  
  376.     Lines->Flush();
  377.     Line->Flush();
  378.  
  379.     is >> numLines;
  380.     is.getline(fileinfo, sizeof(fileinfo));
  381.     Parent->SetCaption(fileinfo);
  382.  
  383.     for (int i = 0; i < numLines; i++) {
  384.       TLine line;
  385.       is >> line;
  386.       Lines->Add(line);
  387.     }
  388.   }
  389.   IsNewFile = IsDirty = false;
  390.   Invalidate();
  391. }
  392.  
  393. class TDrawApp : public TApplication {
  394.   public:
  395.     TDrawApp() : TApplication() {}
  396.  
  397.     void InitMainWindow();
  398. };
  399.  
  400. void
  401. TDrawApp::InitMainWindow()
  402. {
  403.   // Construct the decorated frame window
  404.   TDecoratedFrame* frame = new TDecoratedFrame(0, "Drawing Pad", new TDrawWindow, true);
  405.  
  406.   // Construct a status bar
  407.   TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed);
  408.  
  409.   // Construct a control bar
  410.   TControlBar* cb = new TControlBar(frame);
  411.   cb->Insert(*new TButtonGadget(CM_FILENEW, CM_FILENEW, TButtonGadget::Command));
  412.   cb->Insert(*new TButtonGadget(CM_FILEOPEN, CM_FILEOPEN, TButtonGadget::Command));
  413.   cb->Insert(*new TButtonGadget(CM_FILESAVE, CM_FILESAVE, TButtonGadget::Command));
  414.   cb->Insert(*new TButtonGadget(CM_FILESAVEAS, CM_FILESAVEAS, TButtonGadget::Command));
  415.   cb->Insert(*new TSeparatorGadget);
  416.   cb->Insert(*new TButtonGadget(CM_PENSIZE, CM_PENSIZE, TButtonGadget::Command));
  417.   cb->Insert(*new TButtonGadget(CM_PENCOLOR, CM_PENCOLOR, TButtonGadget::Command));
  418.   cb->Insert(*new TSeparatorGadget);
  419.   cb->Insert(*new TButtonGadget(CM_ABOUT, CM_ABOUT, TButtonGadget::Command));
  420.  
  421.   // Insert the status bar and control bar into the frame
  422.   frame->Insert(*sb, TDecoratedFrame::Bottom);
  423.   frame->Insert(*cb, TDecoratedFrame::Top);
  424.  
  425.   // Set the main window and its menu
  426.   SetMainWindow(frame);
  427.   GetMainWindow()->AssignMenu("COMMANDS");
  428. }
  429.  
  430. int
  431. OwlMain(int /*argc*/, char* /*argv*/ [])
  432. {
  433.   return TDrawApp().Run();
  434. }
  435.  
  436. ostream&
  437. operator <<(ostream& os, const TLine& line)
  438. {
  439.   // Write the number of points in the line
  440.   os << line.GetItemsInContainer();
  441.  
  442.   // Get and write pen attributes.
  443.   os << ' ' << line.Color << ' ' << line.PenSize;
  444.  
  445.   // Get an iterator for the array of points
  446.   TPointsIterator j(line);
  447.  
  448.   // While the iterator is valid (i.e. we haven't run out of points)
  449.   while(j)
  450.     // Write the point from the iterator and increment the array.
  451.     os << j++;
  452.   os << '\n';
  453.  
  454.   // return the stream object
  455.   return os;
  456. }
  457.  
  458. istream&
  459. operator >>(istream& is, TLine& line)
  460. {
  461.   unsigned numPoints;
  462.   is >> numPoints;
  463.  
  464.   COLORREF color;
  465.   int penSize;
  466.   is >> color >> penSize;
  467.   line.SetPen(TColor(color), penSize);
  468.  
  469.   while (numPoints--) {
  470.     TPoint point;
  471.     is >> point;
  472.     line.Add(point);
  473.   }
  474.  
  475.   // return the stream object
  476.   return is;
  477. }
  478.